#include "b_config.h"
#include "b_os.h"
#include "ciu32l051_std.h"
#include "hal/inc/b_hal_lcd.h"

/**
 * \addtogroup B_MCU
 * \{
 */

/**
 * \addtogroup CIU32L051x
 * \{
 */

/**
 * \addtogroup LCD
 * \{
 */

/**
 * \defgroup LCD_Private_Variables
 * \{
 */

// LCD segment mapping for CIU32L051x
// static const struct {
//     GPIO_TypeDef *port;
//     uint16_t pin;
// } lcd_seg_map[] = {
//     {GPIOA, GPIO_PIN_0},  // SEG0
//     {GPIOA, GPIO_PIN_1},  // SEG1
//     {GPIOA, GPIO_PIN_2},  // SEG2
//     {GPIOA, GPIO_PIN_3},  // SEG3
//     {GPIOA, GPIO_PIN_4},  // SEG4
//     {GPIOA, GPIO_PIN_5},  // SEG5
//     {GPIOA, GPIO_PIN_6},  // SEG6
//     {GPIOA, GPIO_PIN_7},  // SEG7
//     {GPIOB, GPIO_PIN_0},  // SEG8
//     {GPIOB, GPIO_PIN_1},  // SEG9
//     {GPIOB, GPIO_PIN_2},  // SEG10
//     {GPIOB, GPIO_PIN_3},  // SEG11
//     {GPIOB, GPIO_PIN_4},  // SEG12
//     {GPIOB, GPIO_PIN_5},  // SEG13
//     {GPIOB, GPIO_PIN_6},  // SEG14
//     {GPIOB, GPIO_PIN_7},  // SEG15
//     {GPIOC, GPIO_PIN_0},  // SEG16
//     {GPIOC, GPIO_PIN_1},  // SEG17
//     {GPIOC, GPIO_PIN_2},  // SEG18
//     {GPIOC, GPIO_PIN_3},  // SEG19
//     {GPIOC, GPIO_PIN_4},  // SEG20
//     {GPIOC, GPIO_PIN_5},  // SEG21
//     {GPIOC, GPIO_PIN_6},  // SEG22
//     {GPIOC, GPIO_PIN_7},  // SEG23
//     {GPIOD, GPIO_PIN_0},  // SEG24
//     {GPIOD, GPIO_PIN_1},  // SEG25
//     {GPIOD, GPIO_PIN_2},  // SEG26
//     {GPIOD, GPIO_PIN_3},  // SEG27
//     {GPIOD, GPIO_PIN_4},  // SEG28
//     {GPIOD, GPIO_PIN_5},  // SEG29
//     {GPIOD, GPIO_PIN_6},  // SEG30
//     {GPIOD, GPIO_PIN_7},  // SEG31
// };

// LCD COM pins
// static const struct {
//     GPIO_TypeDef *port;
//     uint16_t pin;
// } lcd_com_map[] = {
//     {GPIOE, GPIO_PIN_0},  // COM0
//     {GPIOE, GPIO_PIN_1},  // COM1
//     {GPIOE, GPIO_PIN_2},  // COM2
//     {GPIOE, GPIO_PIN_3},  // COM3
// };

// 添加全局RAM缓冲区
static uint32_t lcd_ram_buffer[LCD_COM_MAX] = {0}; // 假设有4个COM

/**
 * \}
 */

/**
 * \defgroup LCD_Private_Functions
 * \{
 */
int bMcuLcdSetSeg(bLcdSeg_t seg, bLcdCom_t com, uint8_t state);
static void lcd_gpio_init(void)
{
    // std_gpio_init_t gpio_init = {0};

    // // Enable GPIO clocks
    // std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);
    // std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);
    // std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOC);
    // std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOD);
    // std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOE);

    // // Configure SEG pins
    // gpio_init.mode = GPIO_MODE_ALTERNATE;
    // gpio_init.pull = GPIO_NOPULL;
    // gpio_init.alternate = GPIO_AF11_LCD;

    // for (int i = 0; i < sizeof(lcd_seg_map) / sizeof(lcd_seg_map[0]); i++) {
    //     gpio_init.pin = lcd_seg_map[i].pin;
    //     std_gpio_init(lcd_seg_map[i].port, &gpio_init);
    // }

    // // Configure COM pins
    // for (int i = 0; i < sizeof(lcd_com_map) / sizeof(lcd_com_map[0]); i++) {
    //     gpio_init.pin = lcd_com_map[i].pin;
    //     std_gpio_init(lcd_com_map[i].port, &gpio_init);
    // }
}

/**
 * \}
 */
static void bMcuLcdGpioConfig()
{
    std_gpio_init_t lcd_gpio_config = {0};

    std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA | RCC_PERIPH_CLK_GPIOB | RCC_PERIPH_CLK_GPIOC);

    lcd_gpio_config.pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_15 | GPIO_PIN_10 |
                          GPIO_PIN_11 | GPIO_PIN_12;
    lcd_gpio_config.mode      = GPIO_MODE_ALTERNATE;
    lcd_gpio_config.alternate = GPIO_AF3_LCD;
    std_gpio_init(GPIOA, &lcd_gpio_config);

    lcd_gpio_config.pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 |
                          GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                          GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
    std_gpio_init(GPIOB, &lcd_gpio_config);

    lcd_gpio_config.pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11;
    std_gpio_init(GPIOC, &lcd_gpio_config);
}
/**
 * @brief  LCDÊ±ÖÓÔ´ÅäÖÃ
 * @retval ÎÞ
 */
static void lcd_clock_config(void)
{
    std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_PMU);

    std_pmu_vaon_write_enable();

    std_rcc_lxtal_drive_mode_config(RCC_LXTAL_DRIVE_MODE_ENHANCE);
    std_rcc_lxtal_drive_config(RCC_LXTAL_DRIVE_LEVEL2);

    /* Ê¹ÄÜLXTAL */
    std_rcc_lxtal_enable(RCC_LXTAL_ON);

    while (!std_rcc_get_lxtal_ready())
        ;

    std_rcc_set_rtcclk_source(RCC_RTC_ASYNC_CLK_SRC_LXTAL);
    std_pmu_vaon_write_disable();
}

static void lcd_init(void)
{
    std_lcd_init_t lcd_config = {0};

    std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_LCD);
    /* LCD·À¼«»¯ */
    std_lcd_set_anti_polar(LCD_ANTIPOLAR_GND);

    /* LCD²ÎÊýÅäÖÃ */
    lcd_config.mux_segment =
        LCD_MUX_SEGMENT_ENABLE; /* 1/6 ºÍ 1/4dutyÐèÊ¹ÄÜÇø¶Î¶àÂ·¸´ÓÃ£¬1/8dutyÎªÎÞ¹ØÏî */
    lcd_config.bias         = LCD_BIAS_1_3;
    lcd_config.duty         = LCD_DUTY_1_4;
    lcd_config.driver_mode  = LCD_DRIVER_MODE_INNER_RESISTER;
    lcd_config.prescaler    = LCD_PRESCALER_4; /* ÅäÖÃÖ¡ËÙÂÊÎª32Hz */
    lcd_config.divider      = LCD_DIVIDER_16;
    lcd_config.high_drive   = LCD_HIGH_DRIVE;
    lcd_config.vlcd_voltage = LCD_INNER_RESISTER_0_902_VDD; /* VLCD = VDD */ 

    /* LCD ³õÊ¼»¯ */
    std_lcd_init(&lcd_config);
    /* LCD COMºÍSEG²¨ÐÎÊä³ö */
    std_lcd_set_scoc(LCD_SCOC_OUT);
}
/**
 * \defgroup LCD_Exported_Functions
 * \{
 */

int bMcuLcdInit(bLcdConfig_t *config)
{
    bMcuLcdGpioConfig();
    lcd_clock_config();
    lcd_init();
    // std_lcd_write(LCD_RAM_REGISTER0, 0, 0xFFFFFF);
    // std_lcd_write(LCD_RAM_REGISTER1, 0, 0xFFFFFF);
    // std_lcd_write(LCD_RAM_REGISTER2, 0, 0xFFFFFF);
    // std_lcd_write(LCD_RAM_REGISTER3, 0, 0xFFFFFF);

    return 0;
}

int bMcuLcdDeInit(void)
{
    // Disable LCD
    // std_lcd_disable();

    // // Disable LCD clock
    // std_rcc_apb1_clk_disable(RCC_PERIPH_CLK_LCD);

    return 0;
}

int bMcuLcdOn(void)
{
    std_lcd_enable();
    return 0;
}

int bMcuLcdOff(void)
{
    std_lcd_disable();
    return 0;
}

int bMcuLcdSetContrast(uint8_t contrast)
{
    if (contrast > 100)
        return -1;

    // std_lcd_set_contrast(contrast);
    return 0;
}

int bMcuLcdClear(void)
{
    // Clear all segments
    for (int i = 0; i < LCD_SEG_MAX; i++)
    {
        bMcuLcdSetSeg(i, LCD_COM_0, 0);
        bMcuLcdSetSeg(i, LCD_COM_1, 0);
        bMcuLcdSetSeg(i, LCD_COM_2, 0);
        bMcuLcdSetSeg(i, LCD_COM_3, 0);
    }
    return 0;
}

int bMcuLcdSetSeg(bLcdSeg_t seg, bLcdCom_t com, uint8_t state)
{
    if (seg >= LCD_SEG_MAX || com >= LCD_COM_MAX)
        return -1;

    uint32_t mask;  // 位掩码
    
    // 创建掩码
    mask = (1U << seg);
  //  b_log("ram_index %d, mask %d, state %d\n", com, mask, state);
    
    // 在缓冲区中修改对应的位
    if (state)
    {
        lcd_ram_buffer[com] |= mask;  // 设置位
    }
    else
    {
        lcd_ram_buffer[com] &= ~mask;  // 清除位
    }
    
    // 将缓冲区的值写入到硬件寄存器
    LCD->RAM[com] = lcd_ram_buffer[com];
   // b_log("set buffer: %d, actual: %d\n", lcd_ram_buffer[com], LCD->RAM[com]);

    return 0;
}
uint8_t bMcuLcdReadSegState(bLcdSeg_t seg, bLcdCom_t com)
{
    // 检查参数有效性
    if (seg >= LCD_SEG_MAX || com >= LCD_COM_MAX)
        return 0;

    // 从缓冲区读取状态
    return (lcd_ram_buffer[com] & (1U << seg)) ? 1 : 0;
}

/**
 * \}
 */

/**
 * \}
 */

/**
 * \}
 */

/**
 * \}
 */

/************************ Copyright (c) 2024 Bean *****END OF FILE****/